home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.02 Feb 95 / Yenta / C Libraries / FileTools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-04  |  11.6 KB  |  415 lines  |  [TEXT/KAHL]

  1. #include <FileTools.h>
  2. #include <script.h>        // for TruncString
  3.  
  4. /*-----------------------------------------------------------------*/
  5. /*------------------------ GLOBAL VARIABLES -----------------------*/
  6. /*-----------------------------------------------------------------*/
  7.  
  8. StringPtr    gPrevSelectedName = NULL;
  9. Boolean        gDirSelectionFlag = FALSE;
  10.  
  11. StringPtr    TDName;        // used in TraverseDirectory
  12. CInfoPBPtr    TDCPB;        // used in TraverseDirectory
  13. OSErr        TDErr;        // used in TraverseDirectory
  14.  
  15.  
  16. void    RecursiveBuild (long dirID, FDActionProc FileAction,
  17.                         FDActionProc FolderAction, void *UserData);
  18.  
  19. /*-----------------------------------------------------------------*/
  20. /*---------------------- SF UTILITY ROUTINES ----------------------*/
  21. /*-----------------------------------------------------------------*/
  22.  
  23.     long    DirIDFromFSSpec (FSSpecPtr theSpec)
  24.     /* given a name, parent ID, and volrefnum in theSpec, return  */
  25.     /* the directory ID of the directory they specify.  Return -1 */
  26.     /* if an error occurs */
  27.     {
  28.         long    theID = -1;
  29.         OSErr    ErrCode;
  30.         
  31.         CInfoPBPtr    PB = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  32.         
  33.         if (PB)
  34.           {
  35.               PB->dirInfo.ioDrDirID = theSpec->parID;
  36.               PB->dirInfo.ioCompletion = NULL;
  37.              PB->dirInfo.ioFDirIndex = 0;
  38.              PB->dirInfo.ioNamePtr = theSpec->name;
  39.              PB->dirInfo.ioVRefNum = theSpec->vRefNum;
  40.               
  41.               if ((ErrCode = PBGetCatInfo (PB, FALSE)) == noErr)
  42.                 theID = PB->dirInfo.ioDrDirID;
  43.               
  44.               DisposPtr((Ptr)PB);
  45.           }
  46.         
  47.         return theID;
  48.     }
  49.  
  50. /*-----------------------------------------------------------------*/
  51.  
  52.     long    GetCurrentDirectory (void)
  53.     /* return the current directory */
  54.     {
  55.         return *((long *)0x0398);
  56.     }
  57.  
  58. /*-----------------------------------------------------------------*/
  59.  
  60.     short    GetCurrentVolume (void)
  61.     /* return the current volume */
  62.     {
  63.         return (-1 * (*((short *)0x0214)));
  64.     }
  65.  
  66. /*-----------------------------------------------------------------*/
  67.  
  68.     void    SetCurrentVolume (short newVRefNum)
  69.     /* set the current volume */
  70.     {
  71.     //    *((short *)0x0214)) = newVRefNum;
  72.     }
  73.  
  74. /*-----------------------------------------------------------------*/
  75.  
  76.     void    SetCurrentDirectory (long newDirID)
  77.     /* set the current directory */
  78.     {
  79.         *((long *)0x0398) = newDirID;
  80.     }
  81.  
  82. /*-----------------------------------------------------------------*/
  83.  
  84.     pascal Boolean GetFolderFileFilter (ParmBlkPtr PB, void *myDataPtr)
  85.     /* return true if the passed file/folder is NOT a folder */
  86.     {
  87.         CInfoPBPtr    CPB = (CInfoPBPtr)PB;
  88.         
  89.         return ((0x0010 & CPB->dirInfo.ioFlAttrib) == 0);
  90.     }
  91.  
  92. /*-----------------------------------------------------------------*/
  93. /*------------------------- GetFolder -----------------------------*/
  94. /*-----------------------------------------------------------------*/
  95.  
  96.     void    SetButtonTitle    (Handle theButton, StringPtr theName, 
  97.                              Rect *itsBounds)
  98.     /* set the title of the button to the specified string */
  99.     {
  100.         short    result, width;
  101.         Str255    STemp;
  102.     
  103.         if (gPrevSelectedName)
  104.           DisposPtr ((Ptr)gPrevSelectedName);
  105.         gPrevSelectedName = String2String(theName);
  106.         
  107.         width = (itsBounds->right - itsBounds->left) - 
  108.                 StringWidth ("\pSelect \"\"") + CharWidth (' ');
  109.         result = TruncString (width, theName, smTruncMiddle);
  110.         PStrCat (255, STemp, 3, "\pSelect \"", theName, "\p\"");
  111.         SetCTitle ((ControlHandle)theButton, STemp);
  112.         ValidRect (itsBounds);
  113.     }
  114.  
  115. /*-----------------------------------------------------------------*/
  116.  
  117.     pascal short    GetFolderDlogHook (short item, DialogPtr theDialog,
  118.                                        void *myDataPtr)
  119.     {
  120.         typedef     StandardFileReply *SFRPtr;
  121.         #define        kDirButton    10
  122.         
  123.         short        myType;
  124.         Handle        myHandle;
  125.         Rect        myRect;
  126.         Str255        myName;
  127.         CInfoPBRec    myPB;
  128.         SFRPtr        mySFRPtr;
  129.         OSErr        myErr;
  130.         short        retVal = item;
  131.         
  132.         if (GetWRefCon((WindowPtr)theDialog) != (long)(sfMainDialogRefCon))
  133.           return retVal;
  134.           
  135.         GetDItem (theDialog, kDirButton, &myType, &myHandle, &myRect);
  136.         if (item == sfHookFirstCall)
  137.           {
  138.               myPB.hFileInfo.ioCompletion = NULL;
  139.               myPB.hFileInfo.ioNamePtr = (StringPtr)(&myName);
  140.               myPB.hFileInfo.ioVRefNum = GetCurrentVolume();
  141.               myPB.dirInfo.ioFDirIndex = -1;
  142.               myPB.hFileInfo.ioDirID = GetCurrentDirectory();
  143.             myErr = PBGetCatInfo(&myPB, FALSE);
  144.             SetButtonTitle (myHandle, myName, &myRect);
  145.           }    // if
  146.         else
  147.           {
  148.               mySFRPtr = (SFRPtr)myDataPtr;
  149.               if (mySFRPtr->sfIsFolder || mySFRPtr->sfIsVolume)
  150.                 CopyString (mySFRPtr->sfFile.name, myName);
  151.               else
  152.                 {
  153.                   myPB.hFileInfo.ioCompletion = NULL;
  154.                   myPB.hFileInfo.ioNamePtr = (StringPtr)(&myName);
  155.                   myPB.hFileInfo.ioVRefNum = mySFRPtr->sfFile.vRefNum;
  156.                   myPB.dirInfo.ioFDirIndex = -1;
  157.                   myPB.hFileInfo.ioDirID = mySFRPtr->sfFile.parID;
  158.                   myErr = PBGetCatInfo (&myPB, FALSE);
  159.                 }    // else
  160.                 
  161.               if (PStrCmp (myName, gPrevSelectedName) != 0)
  162.                 SetButtonTitle (myHandle, myName, &myRect);
  163.                 
  164.               switch (item) {
  165.                   case kDirButton :
  166.                       return sfItemCancelButton;
  167.                       break;
  168.                   case sfItemCancelButton :
  169.                       gDirSelectionFlag = FALSE;
  170.                       break;
  171.               }    //switch
  172.           }    // else
  173.         
  174.         return retVal;
  175.                 
  176.     }    // GetFolderDlogHook
  177.  
  178. /*-----------------------------------------------------------------*/
  179.  
  180.     void    GetDirectory (StandardFileReply *SFReply)
  181.     {
  182.         SFTypeList                myTypes;
  183.         Point                    myPoint = {-1, -1};
  184.         short                    myNumTypes = -1;
  185.         ModalFilterYDProcPtr    myModalFilter = NULL;
  186.         short                    myActiveList = -1;
  187.         ActivateYDProcPtr        myActivateProc = NULL;
  188.         Str255                    myName;
  189.         
  190.         gDirSelectionFlag    =    TRUE;
  191.         if (gPrevSelectedName)
  192.           DisposPtr((Ptr)gPrevSelectedName);
  193.         
  194.         CustomGetFile (&GetFolderFileFilter,
  195.                         myNumTypes, 
  196.                         myTypes, 
  197.                         SFReply, 
  198.                         12800, 
  199.                         myPoint, 
  200.                         &GetFolderDlogHook,
  201.                         myModalFilter, 
  202.                         &myActiveList, 
  203.                         myActivateProc, 
  204.                         SFReply);
  205.         
  206.         if (gDirSelectionFlag)
  207.           SFReply->sfGood = TRUE;
  208.         
  209.         if (gDirSelectionFlag && SFReply->sfIsVolume)
  210.           PStrCat (255, myName, 2, SFReply->sfFile.name, "\p:");
  211.         else
  212.           CopyString (SFReply->sfFile.name, myName);
  213.           
  214.         if (gDirSelectionFlag && SFReply->sfIsVolume)
  215.           CopyString (myName, SFReply->sfFile.name);
  216.         else
  217.         if (gDirSelectionFlag)
  218.           CopyString (gPrevSelectedName, SFReply->sfFile.name);
  219.         
  220.         gDirSelectionFlag = FALSE;
  221.     }
  222.  
  223. /*-----------------------------------------------------------------*/
  224. /*--------------------- TraverseDirectory -------------------------*/
  225. /*-----------------------------------------------------------------*/
  226.  
  227.     void    TraverseDirectory (FSSpec *Directory, FDActionProc FileAction,
  228.                                FDActionProc FolderAction, void *UserData)
  229.     /* Given the specification of a directory, traverse its contents */
  230.     /* recursively, applying FileAction to each file, and FolderAction */
  231.     /* to each folder/directory that is encountered */
  232.     {
  233.         TDErr = noErr;
  234.         TDName = (StringPtr)NewPtrClear(64);
  235.         TDCPB = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  236.         
  237.         if (TDCPB && TDName)
  238.           {
  239.             TDCPB->hFileInfo.ioNamePtr = TDName;
  240.             TDCPB->hFileInfo.ioVRefNum = Directory->vRefNum;
  241.             RecursiveBuild (DirIDFromFSSpec(Directory), FileAction,
  242.                             FolderAction, UserData);         
  243.           }
  244.     
  245.         if (TDName)
  246.           {
  247.             DisposPtr((Ptr)TDName);
  248.             TDName = NULL;
  249.           }
  250.         if (TDCPB)
  251.           {
  252.               DisposPtr((Ptr)TDCPB);
  253.             TDName = NULL;
  254.           }
  255.     }
  256.  
  257. /*-----------------------------------------------------------------*/
  258.  
  259.     void    RecursiveBuild (long dirID, FDActionProc FileAction,
  260.                             FDActionProc FolderAction, void *UserData)
  261.     /* this is the routine which does all of the traversal gruntwork */
  262.     /* for TraverseDirectory */
  263.     {
  264.         short    index = 1;
  265.         
  266.         do
  267.           {
  268.               TDCPB->hFileInfo.ioFDirIndex = index;
  269.               TDCPB->dirInfo.ioDrDirID = dirID;
  270.               
  271.               TDErr = PBGetCatInfo(TDCPB, FALSE);
  272.               
  273.               if (TDErr == noErr)
  274.                 if (0x0010 & TDCPB->dirInfo.ioFlAttrib)
  275.                     {    // we have a directory; perform user action
  276.                         // on it, then traverse it
  277.                       if (FolderAction)
  278.                         (FolderAction)(TDCPB, UserData);
  279.                       RecursiveBuild (TDCPB->dirInfo.ioDrDirID, FileAction,
  280.                                         FolderAction, UserData);
  281.                       TDErr = noErr;
  282.                     }
  283.                else    // we have a file; perform user action on it
  284.                     if (FileAction)
  285.                       (FileAction)(TDCPB, UserData);
  286.                 
  287.               index++;
  288.           } while (TDErr == noErr);
  289.     }
  290.     
  291. /*-----------------------------------------------------------------*/
  292. /*--------------------- FSSpecFromSFReply -------------------------*/
  293. /*-----------------------------------------------------------------*/
  294.  
  295.     FSSpecPtr    FSSpecFromSFReply (SFReply *SFR)
  296.     /* given a file specification from one of the standard file */
  297.     /* routines, return an FSSpec for use with the low level file */
  298.     /* routines. Return NULL if it cannot be constructed */
  299.     {    
  300.         CInfoPBPtr    myPB = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  301.         FSSpecPtr fileSpec = NULL;
  302.         OSErr    ErrCode;
  303.         
  304.         if (myPB)
  305.           {
  306.               myPB->hFileInfo.ioFDirIndex = 0;
  307.               myPB->hFileInfo.ioVRefNum = SFR->vRefNum;
  308.               myPB->hFileInfo.ioNamePtr = SFR->fName;
  309.              if ((ErrCode = PBGetCatInfo (myPB, FALSE)) == noErr)
  310.                {
  311.                 fileSpec = (FSSpecPtr)NewPtrClear(sizeof(FSSpec));
  312.                    if (fileSpec)
  313.                      FSMakeFSSpec (myPB->hFileInfo.ioVRefNum, 
  314.                                    myPB->hFileInfo.ioFlParID,
  315.                                    myPB->hFileInfo.ioNamePtr,
  316.                                    fileSpec);
  317.                }
  318.           }
  319.           
  320.         DisposPtr((Ptr)myPB);
  321.         return fileSpec;
  322.     }
  323.  
  324. /*-----------------------------------------------------------------*/
  325. /*---------------------- FSSpecFromCInfo --------------------------*/
  326. /*-----------------------------------------------------------------*/
  327.  
  328.     FSSpecPtr    FSSpecFromCInfo (CInfoPBPtr CB)
  329.     /* construct and return an FSSpec record describing the file/folder */
  330.     /* whose information is passed in the CBInfoRec structure */
  331.     {
  332.         FSSpecPtr fileSpec = NULL;
  333.  
  334.         if (CB)
  335.           {
  336.             fileSpec = (FSSpecPtr)NewPtrClear(sizeof(FSSpec));
  337.                if (fileSpec)
  338.                  {
  339.                      if (0x0010 & CB->dirInfo.ioFlAttrib)    // directory
  340.                      FSMakeFSSpec (CB->dirInfo.ioVRefNum, 
  341.                                    CB->dirInfo.ioDrParID,
  342.                                    CB->dirInfo.ioNamePtr,
  343.                                    fileSpec);
  344.                      else                                    // file
  345.                      FSMakeFSSpec (CB->hFileInfo.ioVRefNum, 
  346.                                    CB->hFileInfo.ioFlParID,
  347.                                    CB->hFileInfo.ioNamePtr,
  348.                                    fileSpec);
  349.                  }
  350.           }
  351.           
  352.         return fileSpec;
  353.     }
  354.  
  355. /*-----------------------------------------------------------------*/
  356. /*------------------------ FullPathName ---------------------------*/
  357. /*-----------------------------------------------------------------*/
  358.  
  359.     StringPtr    PathNameFromFSSpec (FSSpecPtr fileID)
  360.     /* given the specification of a file, return its full path name */
  361.     {
  362.         CInfoPBPtr    myPB = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  363.         Str63        dirName;
  364.         Str255        fullPath, STemp;
  365.         OSErr        myErr;
  366.  
  367.         
  368.         if (!myPB || !fileID)
  369.           return NULL;
  370.           
  371.         fullPath[0] = 0;
  372.         myPB->dirInfo.ioNamePtr = dirName;
  373.         myPB->dirInfo.ioVRefNum = fileID->vRefNum;
  374.         myPB->dirInfo.ioDrParID = fileID->parID;
  375.         myPB->dirInfo.ioFDirIndex = -1;
  376.         
  377.         do 
  378.           {
  379.             myPB->dirInfo.ioDrDirID = myPB->dirInfo.ioDrParID;
  380.             myErr = PBGetCatInfo (myPB, FALSE);
  381.             PStrCat (255, STemp, 3, dirName, "\p:", fullPath);
  382.             CopyString (STemp, fullPath);
  383.           } while (myPB->dirInfo.ioDrDirID != fsRtDirID);
  384.         
  385.         DisposPtr((Ptr)myPB);
  386.         
  387.         PStrCat (255, STemp, 2, fullPath, fileID->name);
  388.         
  389.         return String2String (STemp);
  390.     }
  391.     
  392. /*-----------------------------------------------------------------*/
  393. /*------------------------ FullPathName ---------------------------*/
  394. /*-----------------------------------------------------------------*/
  395.  
  396.     StringPtr    PathNameFromCInfo (CInfoPBPtr CB)
  397.     /* given the specification of a file, return its full path name */
  398.     {
  399.         FSSpecPtr    theSpec;
  400.         StringPtr    theName = NULL;
  401.         
  402.         if (!CB)
  403.           return NULL;
  404.           
  405.         theSpec = FSSpecFromCInfo(CB);
  406.           
  407.         if (theSpec)
  408.           {
  409.               theName = PathNameFromFSSpec (theSpec);
  410.               DisposPtr((Ptr)theSpec);
  411.           }
  412.         
  413.         return theName;
  414.     }
  415.